<script setup lang="ts">
import { NSpace, NInput, NButton, NSelect, NRadio, NInputNumber, NImage, useMessage } from 'naive-ui'
import { ref } from 'vue';
import { generateImage } from '../apis/openai'
import { useImageStore } from '../stores/image'
import { v4 } from 'uuid'


const imageStore = useImageStore()
const message = useMessage()

const dallE3sizeOptions = ['1024x1024', '1792x1024', '1024x1792'].map(item => ({label: item, value: item}))
const dallE2sizeOptions = ['256x256', '512x512','1024x1024'].map(item => ({label: item, value: item}))


const dallE3styleOptions = ['vivid', 'natural'].map(item => ({label: item, value: item}))
const dallE3qualityOptions = ['standard', 'hd'].map(item => ({label: item, value: item}))

const generateDisabled = ref(false)

const isFormatUrl = ref(true)

const isDallE3 = ref(true)

const n = ref(1)
const dallE3size = ref('1024x1024')
const dallE2size = ref('256x256')
const quality = ref('standard')
const style = ref('vivid')
const prompt = ref('')

const images = ref<OpenAi.Text2ImageResponse[]>([])

let requestParam: null | OpenAi.Text2ImageRequest = null

function generate() {
    const inputPrompt = prompt.value.trim()
    if (inputPrompt.length == 0) {
        return
    }
    generateDisabled.value = true
    images.value = []
    requestParam = null

    const params = {
        prompt: inputPrompt,
        response_format: isFormatUrl.value ? 'url': 'b64_json',
        n: 1,
        size: '',
        model: 'dall-e-3'
    } as OpenAi.Text2ImageRequest
    if (isDallE3.value) {
        params.size = dallE3size.value
        params.quality = quality.value
        params.style = style.value
    } else {
        params.model = 'dall-e-2'
        params.size = dallE2size.value
        params.n = n.value
    }
    generateImage(params).then(res => {
        if (!res) return
        images.value = res
        requestParam = params
    }).catch((err: Error) => {
        console.log(err)
        message.error(err.message)
    }).finally(() => {
        generateDisabled.value = false
    })
}

function save() {
    const params = requestParam
    if (params == null || images.value.length == 0) return
    images.value.forEach(item => {
        imageStore.add({
            id: v4(),
            model: params.model,
            prompt: params.prompt,
            size: params.size,
            url: item.url,
            revised_prompt: item.revised_prompt,
            b64_json: item.b64_json,
            style: params.style,
            quality: params.quality,
            created_at: Date.now()
        })
    })
}

</script>

<template>

    <n-space vertical>
        <n-input v-model:value="prompt" :autosize="{minRows: 3, maxRows: 5}" type="textarea" style="width: 800px; text-align: left;" clearable/>
        <n-space>
            <n-radio :checked="isDallE3" value="dall-e-3" name="model" @change="isDallE3=true">DALL-E 3</n-radio>
            <n-radio :checked="!isDallE3" value="dall-e-2" name="model" @change="isDallE3=false">DALL-E 2</n-radio>
        </n-space>
        <n-space>
            <n-space v-if="isDallE3">
                <n-select v-model:value="dallE3size" :options="dallE3sizeOptions" style="width: 160px;"/>
                <n-select v-model:value="quality" :options="dallE3qualityOptions" style="width: 160px;"/>
                <n-select v-model:value="style" :options="dallE3styleOptions" style="width: 160px;"/>
            </n-space>
            <n-space v-else>
                <n-input-number v-model:value="n" 
                    :min="1"
                    :max="10"
                />
                <n-select v-model:value="dallE2size" :options="dallE2sizeOptions" style="width: 160px;" />
            </n-space>
        </n-space>
        <n-space align="center">
            <n-radio :checked="isFormatUrl" value="url" name="format" @change="isFormatUrl=true">url</n-radio>
            <n-radio :checked="!isFormatUrl" value="base64" name="format" @change="isFormatUrl=false">base64</n-radio>
            <n-button @click="generate" type="info" :disabled="generateDisabled">generate</n-button>
            <n-button @click="save" type="success" :disabled="images.length == 0">save</n-button>
        </n-space>
        <n-space>
            <n-image v-for="item of images" :src="item.url || ('data:image/png;base64,' +item.b64_json)" :style="{width: '400px'}"/>
        </n-space>
    </n-space>
</template>